<html>
<head>
	<meta http-equiv="content-type" content="text/html; charset=utf-8">
	<meta http-equiv=MSThemeCompatible Content=Yes>
<hta:application
	id=SesMgr
	applicationName=Session_Manager
	version=1.2
	maximizeButton=no
	icon=sysedit.exe
	innerBorder=no
	scroll=no
	singleinstance=yes
	selection=no
>
<style type="text/css">
	body,table   {font-family:MS Shell Dlg; font-size:8pt; background-color:threedface; margin:2;}
	table   {margin:0;}
	td           {white-space:nowrap;}
	input,button,select,textarea {font-family:MS Shell Dlg; font-size:8pt;}
	fieldset     {cursor:default;margin:0px;text-align:left;padding:4px;padding-top:0px;}
	legend       {margin-bottom:2px; color:blue;}
	label        {cursor: hand; white-space:nowrap;}
</style>
<SCRIPT language=Javascript>
// Session Manager
// Author: mozers™
// ------------------------------------------------
var CmdArg = SesMgr.commandLine.replace(/^".*?" */,'');
var quit = false;
if (/^QUIT /.test(CmdArg)) {
	CmdArg = CmdArg.replace(/^QUIT /,'');
	quit = true;
}

// Подготовка диалогового окна
var width = 300;
var height = 325;
if (CmdArg !== ''){
	window.resizeTo(width,212);
}else{
	window.resizeTo(width,height);
}
var winPosX=screen.width/2;
var winPosY=screen.height/2;
window.moveTo(winPosX-width/2, winPosY-height/2);
document.title = SesMgr.applicationName.replace(/_/g,' ') + ' ' + SesMgr.version;

// ------------------------------------------------
// Пути к SciTE и SciteUserHome относительно этого файла
var scite = "..\\..\\SciTE.exe";
var scite_sessions_path = "..\\..\\home";
var chrNewLine = '…';
// ------------------------------------------------
try {
	var SciTE=new ActiveXObject("SciTE.Helper");
} catch(e) {
	alert("Please install SciTE Helper before!");
	self.close();
}
var WshShell = new ActiveXObject("WScript.Shell");
var fso = new ActiveXObject("Scripting.FileSystemObject");
var ForReading = 1, ForWriting = 2, ForAppending = 8;
var Sessions_Arr = [];
var save_description_edited = false;
var script_path=unescape(window.document.URL).replace(/^.*(\w:\\.*\\).*?$/gi, '$1');

// ------------------------------------------------
// Получение полного пути из относительного
function AbsolutePathName(path){
	if (/^\w:\\/.test(path)) {
		return path;
	}else{
		return script_path+path;
	}
}
scite=AbsolutePathName(scite);
scite_sessions_path=AbsolutePathName(scite_sessions_path);

// ------------------------------------------------
// Преобразование даты создания файла к виду "yy|dd|mm|hh|mm"
function DateString (file_date){
	function format(j){return (j < 10) ? ('0' + j) : j;}
	var x = new Date(file_date);
	var d = format(x.getDate());
	var m = format(x.getMonth()+1);
	var y = format(x.getYear()-2000);
	var h = format(x.getHours());
	var i = format(x.getMinutes());
	return y + '|' + m + '|' + d + '|' + h + '|' + i;
}

// ------------------------------------------------
// Извлекает описание из файла descript.ion
function GetDescript(filename){
	file_descript = scite_sessions_path + '\\descript.ion';
	load_description.value = "";
	if (fso.FileExists(file_descript)) {
		var file = fso.OpenTextFile(file_descript, ForReading);
		var text = file.ReadAll();
		file.Close();
		var re = new RegExp(filename+'"{0,1} ([^\r\n]*)','i');
		if (re.test(text)) {
			var rnl = new RegExp(chrNewLine,'g');
			return text.match(re)[1].replace(rnl,'\r\n');
		}
	}
	return "";
}

// ------------------------------------------------
// функция для сортировки массива в убывающем порядке
function compare(a, b) {
	if (String(a) > String(b)) {return -1;}
	if (String(a) < String(b)) {return 1;}
	return 0;
}

// ------------------------------------------------
// Создает массив сессий (в дальнейшем вся работа ведется с ним)
function CreateSessionArray(){
	var a_folder = fso.GetFolder(scite_sessions_path);
	var the_files = new Enumerator(a_folder.Files);
	for (;!the_files.atEnd();the_files.moveNext()) {
		a_file = the_files.item();
		if ((fso.GetExtensionName(a_file).toUpperCase()=='SESSION')&&(a_file.Name!='SciTE.session')) {
			var session_arr = DateString(a_file.DateLastModified).split("|");
			session_arr.push (a_file.Name.replace(/[.]\w*?$/,''));
			session_arr.push (GetDescript(a_file.Name));
			Sessions_Arr.push (session_arr);
		}
	}
	return Sessions_Arr.sort(compare);
}

// ------------------------------------------------
// Дата сохранения файла сессии
function SesDate(i){
	return Sessions_Arr[i][2]+"."+Sessions_Arr[i][1]+"."+Sessions_Arr[i][0]+" "+Sessions_Arr[i][3]+":"+Sessions_Arr[i][4];
}

// ------------------------------------------------
// Имя файла сессии
function SesFileName(i){
	return Sessions_Arr[i][5];
}

// ------------------------------------------------
// Создает листинг сохраненных сессий
function DialogLoad_SessionList(){
	var html = '';
	for (var i=0; i<Sessions_Arr.length; i++) {
		var option = SesDate(i)+"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"+SesFileName(i);
		html += '<option>'+option;
	}
	// Отображаем список сессий
	select.innerHTML = '<select id="sessions_opt" style="width:100%;" size=14 ondblclick="LoadSession(this.selectedIndex)" onkeydown="LoadOnKey(this.selectedIndex)" onchange="load_description.value = Descript(this.selectedIndex)" onmouseup="ShowRCMenu()">'+html+'</select>';
	if (sessions_opt[0]) {sessions_opt[0].selected = true;}
}

// ------------------------------------------------
// Текст описания сессии
function Descript(i){
	if (Sessions_Arr[i]) {
		return Sessions_Arr[i][6];
	} else {
		return "";
	}
}

// ------------------------------------------------
// Инициализация диалогового окна открытия или сохранения сессии
function Init(cmdline){
	CreateSessionArray();
	// Если в ком.строке запуска имеется параметр, то ...
	if (CmdArg !== ''){
		// ...отображаем диалог сохранения сессии
		self.save.style.display = "inline";
		var opt = "";
		for (var i=0; i<Sessions_Arr.length; i++) {
			opt += '<OPTION>' + SesFileName(i) + '</OPTION>';
		}
		self.ListSessions.innerHTML = '<SELECT id="Sessions" onChange="self.ses_name.value=this.options[this.selectedIndex].innerText; save_description.value = Descript(this.selectedIndex)" style="width:100%">'+opt+'</SELECT>';
		self.ses_name.value = CmdArg;
		self.ses_name.select();
		self.ses_name.focus();
	}else{
		// ...иначе, формируем листинг сохраненных ранее сессий
		DialogLoad_SessionList();
		self.load.style.display = "inline";
		load_description.value = Descript(0);
		self.sessions_opt.focus();
	}
}

// ------------------------------------------------
// Определяет запущен SciTE или нет
function ExistSciTEWindow(){
	var objWMIService = GetObject("winmgmts:\\\\.\\root\\CIMV2");
	var colItems = objWMIService.ExecQuery("SELECT * FROM Win32_Process");
	var enumItems = new Enumerator(colItems);
	for (; !enumItems.atEnd(); enumItems.moveNext()) {
		var objItem = enumItems.item();
		if (objItem.name == "SciTE.exe") {return true;}
	}
	return false;
}

// ------------------------------------------------
// Открытие одной из сохраненных сессий
function LoadSession(i){
	var ses = (scite_sessions_path+'\\'+SesFileName(i)+'.session').replace(/\\/g,"\\\\");
	if (ExistSciTEWindow()) {
		SciTE.Send('loadsession:' + ses);
	} else {
		var cmd = '"' + scite + '" ' + '-property:check.if.already.open=1 "-loadsession:' + ses + '"';
		WshShell.Run(cmd, 1, false);
	}
	self.close();
}

// ------------------------------------------------
// Открытие одной из сохраненных сессий в новом окне
function LoadSessionNewWindow(i){
	var ses = (scite_sessions_path+'\\'+SesFileName(i)+'.session').replace(/\\/g,"\\\\");
	var cmd = '"' + scite + '" ' + '-property:check.if.already.open=0 "-loadsession:' + ses + '"';
	WshShell.Run(cmd, 1, false);
	self.close();
}

// ------------------------------------------------
// Удаление выбранной сессии
function DeleteSession(i){
	fso.DeleteFile(scite_sessions_path+'\\'+SesFileName(i)+'.session', true);
	Sessions_Arr.splice(i, 1);
	DialogLoad_SessionList();
}

// ------------------------------------------------
// Создает одну строку для добавления в descript.ion
function OneLineDescript(file,descr){
	file += '.session';
	if (!/^\w{1,8}\.\w{1,3}$/.test(file)) {
		file = '"'+file+'"';
	}
	return file + ' ' + descr.replace(/\r\n/g,chrNewLine);
}

// ------------------------------------------------
// Сохранение описаний к сессиям в descript.ion
function SaveDescriptIon(){
	var descript_arr = [];
	var new_file = true;
	for (var i=0; i<Sessions_Arr.length; i++) {
		if (ses_name.value != SesFileName(i)) {
			descript_arr.push (OneLineDescript(SesFileName(i), Descript(i)));
		}else{
			descript_arr.push (OneLineDescript(ses_name.value, save_description.value));
			new_file = false;
		}
	}
	if (new_file) {
		descript_arr.push (OneLineDescript(ses_name.value, save_description.value));
	}

	var filename = scite_sessions_path + '\\descript.ion';
	if (fso.FileExists(filename)){
		fso.DeleteFile(filename, true);
	}

	var f = fso.OpenTextFile(filename, ForWriting, true);
	f.Write(descript_arr.join('\r\n'));
	f.Close();

	var file = fso.GetFile(filename);
	file.attributes = 34;
}

// ------------------------------------------------
// Действия при нажатии на кнопку "Save"
function SaveSession(){
	var ses_filename = scite_sessions_path + '\\' + ses_name.value + '.session';
	if (!quit) {
		// сохраняем текущую сессию
		SciTE.Send('savesession:' + ses_filename.replace(/\\/g,"\\\\"));
	} else {
		fso.CopyFile(scite_sessions_path + '\\SciTE.session', ses_filename, true);
	}
	// обновляем descript.ion
	SaveDescriptIon();
	self.close();
}

// ------------------------------------------------
// Показывает контекстное меню по правой кнопке мыши на пункте из списка сессий
function ShowRCMenu(){
	if (event.button==1){return false;}
	RCMenu=window.createPopup(); 
	RCMenu.document.oncontextmenu = function(){return false;};
	with (RCMenu.document.body) {
		style.border = "2px outset";
		bgColor = "buttonface";
		innerHTML = right_click_menu.innerHTML;
	}
	for (i=0;i<RCMenu.document.all.menuitem.length;i++){
		RCMenu.document.all.menuitem[i].onmouseover = function () {this.style.background="activecaption"; this.style.color="highlighttext";};
		RCMenu.document.all.menuitem[i].onmouseout = function () {this.style.background="buttonface"; this.style.color="buttontext";};
	}
	RCMenu.show(0, 0, 0, 0, document.body);
	var w=RCMenu.document.body.scrollWidth+5;
	var h=RCMenu.document.body.scrollHeight+5;
	RCMenu.hide();
	RCMenu.show(event.x,event.y,w,h,document.body);
}

// ------------------------------------------------
// Обработка нажатий клавиш в диалоге загрузки новой сессии
function LoadOnKey(i){
	var keycode = event.keyCode;
	switch(keycode){
		case 27: //Esc
			self.close();
			break;
		case 32: // Space
			LoadSession(i);
			break;
		case 13: // Enter
			if (event.ctrlKey) {
				LoadSessionNewWindow(i);
			}else{
				LoadSession(i);
			}
			break;
		case 46: //Delete
			DeleteSession(i);
			break;
	}
}

// ------------------------------------------------
// Обработка нажатий клавиш в диалоге сохранения сессии
function SaveOnKey(){
	var keycode = event.keyCode;
	switch(keycode){
		case 27: //Esc
			self.close();
			break;
		case 13: // Enter
			SaveSession();
			break;
	}
}

// ------------------------------------------------
// Author: Matt Kruse <matt@mattkruse.com>
// WWW: http://www.mattkruse.com/
function autoComplete (field) {
	var found = false;
	if (field.value.length > 0) {
		for (var i = 0; i < self.Sessions.options.length; i++) {
			if (self.Sessions.options[i].innerText.toUpperCase().indexOf(field.value.toUpperCase()) === 0) {
				found=true;
				break;
			}
		}
	}

	if (!save_description_edited) {
		if (found) { save_description.value = Descript(i); }
		else { save_description.value = ""; }
	}

	if (field.createTextRange) {
		var cursorKeys ="8;46;37;38;39;40;33;34;35;36;45;";
		if (cursorKeys.indexOf(event.keyCode+";") == -1) {
			var r1 = field.createTextRange();
			var oldValue = r1.text;
			var newValue = found ? self.Sessions.options[i].innerText : oldValue;
			if (newValue != field.value) {
				field.value = newValue;
				var rNew = field.createTextRange();
				rNew.moveStart('character', oldValue.length) ;
				rNew.select();
				self.Sessions.options[i].selected="true";
			}
		}
	}
}

</SCRIPT>
<body onLoad="Init(SesMgr.commandLine)">
	<!--- Load Session Dialog --------------------------->
	<div id="load" style="display:none">
		<fieldset style="width:100%; height:99%"><legend>&nbsp;Please select saved session:&nbsp;</legend>
			<TABLE width=100% height=95% cellpadding="0" cellspacing="2" border="0" style="margin:0px;">
			<TR><TD width=100%>
				<div id="select"></div>
			</TD></TR>
			<TR><TD width=100%><font color="blue">Description:</font></TD></TR>
			<TR height=100%><TD width=100%><textarea contentEditable="false" id="load_description" style="width:100%; height:98%;overflow:hidden;"></textarea></TD></TR>
			</TABLE>
	</div>
	<!--- Context Menu --------------------------------->
	<div id="right_click_menu" style="display:none">
		<table cellpadding="2" cellspacing="" border="0" style="background-color:buttonface;font:8pt MS Shell Dlg;margin:1px;">
			<tr id="menuitem" onClick="parent.RCMenu.hide();parent.LoadSession(parent.sessions_opt.selectedIndex);">
			<td style="font:8pt Marlett; color:blue">1</td>
			<td><b>&nbsp;Open</b></td>
			<td><b>&nbsp;Enter</b></td>
			</tr>
			<tr id="menuitem" onClick="parent.RCMenu.hide();parent.LoadSessionNewWindow(parent.sessions_opt.selectedIndex)">
			<td style="font:8pt Marlett; color:blue">2</td>
			<td style="white-space:nowrap">&nbsp;New window</td>
			<td>&nbsp;Ctrl+Enter</td>
			</tr>
			<!-- <tr id="menuitem" onClick="parent.RCMenu.hide();parent.RenameSession()">
			<td style="font:8pt Marlett; color:green">a</td>
			<td>&nbsp;Rename</td>
			<td>&nbsp;F6</td>
			</tr> -->
			<tr id="menuitem" onClick="parent.RCMenu.hide();parent.DeleteSession(parent.sessions_opt.selectedIndex)">
			<td style="font:8pt Marlett; color:red">a</td>
			<td>&nbsp;Delete</td>
			<td>&nbsp;Del</td>
			</tr>
		</table>
	</div>
	<!--- Save Session Dialog --------------------------->
	<div id="save" style="display:none">
	<TABLE width=100% height=100% cellpadding="0" cellspacing="0" border="0">
	<tr height=100%><td>
		<fieldset style="width:100%;height:100%;position:absolute;"><legend>&nbsp;Please save current session:&nbsp;</legend>
			<TABLE width=100% height=94% cellpadding="0" cellspacing="4" border="0">
			<TR><TD colspan="2" width=100%>
				<TABLE width=100% cellpadding="0" cellspacing="0" border="0" style="margin:0px">
					<TR><TD>Name:&nbsp;</TD><TD width=100%><INPUT id="ses_name" TYPE=text value="" style="width:100%" onkeypress="SaveOnKey()" onkeyup="autoComplete(this)"></TD></TR>
					<TR><TD>&nbsp;</TD><td><span id="ListSessions"></span></TD></TR>
				</TABLE>
			</TD></TR>
			<TR><TD colspan="2">Description:</TD></TR>
			<TR height=100%><TD colspan="2"><textarea id="save_description" onkeypress="save_description_edited=true" style="width:100%;height:100%;overflow:hidden;position:absolute;"></textarea></TD></TR>
			<TR>
			<TD align=center><button onClick="self.close()">&nbsp;Cancel&nbsp;</button></TD>
			<TD align=center><button onClick="SaveSession()">&nbsp;&nbsp;&nbsp;Save&nbsp;&nbsp;&nbsp;</button></TD>
			</TR>
			</TABLE>
		</fieldset>
	<tr><td>
			<br><INPUT type="checkbox" id=not_show hidefocus> Do not show this window in next on quit SciTE
	</TABLE>
	</div>
	<!------------------------------------------------>
</body>
</html>
